// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.process.models;

import java.util.ArrayList;
import java.util.List;

import org.dengues.core.components.ENodeParameterName;
import org.dengues.core.components.NodePropertyParameter;
import org.dengues.core.prefs.IDenguesPrefsConstant;
import org.dengues.core.process.CompElement;
import org.dengues.core.process.ICompBlock;
import org.dengues.core.process.ICompBlockExit;
import org.dengues.core.process.ICompConnection;
import org.dengues.core.process.ICompNode;
import org.dengues.core.process.ICompProcess;
import org.dengues.core.process.IGefNode;
import org.dengues.core.property.EParameterFieldCategory;
import org.dengues.core.property.EPropertyCategory;
import org.dengues.core.resource.WarehouseResourceFactory;
import org.dengues.core.warehouse.WarehouseLabelUtil;
import org.dengues.designer.ui.process.editors.BlockEditorInput;
import org.dengues.model.warehouse.ProcessType;
import org.dengues.ui.DenguesUiPlugin;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Point;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.swt.graphics.RGB;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * $Id: Dengues.epf Qiang.Zhang.Adolf@gmail.com 2008-4-13 qiang.zhang $
 * 
 */
public class CompBlock extends CompElement implements ICompBlock {

    private static final long serialVersionUID = 1645645764574443L;

    private final String blockId;

    private CompProcess compProcess;

    private Dimension size = new Dimension(0, 0);

    private Point location = new Point(0, 0);

    private String compName;

    private RGB color;

    public static final String PROP_BLOCK_SIZE = "CompBlock_size"; //$NON-NLS-1$

    public static final String PROP_BLOCK_COLOR = "CompBlock_color"; //$NON-NLS-1$

    public static final String PROP_BLOCK_LOCATION = "CompBlock_location"; //$NON-NLS-1$

    public static final String PROP_BLOCK_NAME = "CompBlock_name"; //$NON-NLS-1$

    public CompBlock(String uuid, String sname) {
        String dName = sname;
        String cName = sname;
        if (uuid == null) {
            uuid = WarehouseResourceFactory.getEMFId();
        } else {
            ProcessType blockType = WarehouseLabelUtil.getBlockType(uuid);
            if (blockType != null) {
                dName = blockType.getName();
                cName = blockType.getComment();
            }
        }
        this.blockId = uuid;
        this.compName = sname;

        NodePropertyParameter parameter = new NodePropertyParameter();
        parameter.setFieldCategory(EParameterFieldCategory.TEXT);
        parameter.setField(EParameterFieldCategory.TEXT.getName());
        parameter.setPropertyCategory(EPropertyCategory.PROPERTY);
        parameter.setShow(true);
        parameter.setName(ENodeParameterName.COMPONENT_NAME.getName());
        parameter.setDisplayName(ENodeParameterName.COMPONENT_NAME.getDisplayName());
        parameter.setNbRow(1);
        parameter.setReadOnly(true);
        parameter.setValue(dName);
        addElementParameters(parameter);

        parameter = new NodePropertyParameter();
        parameter.setFieldCategory(EParameterFieldCategory.TEXT);
        parameter.setField(EParameterFieldCategory.TEXT.getName());
        parameter.setPropertyCategory(EPropertyCategory.PROPERTY);
        parameter.setShow(true);
        parameter.setName(ENodeParameterName.DB_COMMENT.getName());
        parameter.setDisplayName(ENodeParameterName.DB_COMMENT.getDisplayName());
        parameter.setNbRow(2);
        parameter.setReadOnly(true);
        parameter.setValue(cName);
        addElementParameters(parameter);
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.designer.ui.gef.models.Element#getElementName()
     */
    @Override
    public String getCompName() {
        return this.compName;
    }

    /**
     * Getter for color.
     * 
     * @return the color
     */
    @Override
    public RGB getColor() {
        return this.color;
    }

    /**
     * Sets the color.
     * 
     * @param color the color to set
     */
    public void setColor(RGB color) {
        if (this.color == null
                || this.color.equals(PreferenceConverter.getColor(DenguesUiPlugin.getDefault().getPreferenceStore(),
                        IDenguesPrefsConstant.DESIGNER_COLOR_BLOCK))) {
            this.color = color;
            fireStructureChange(PROP_BLOCK_COLOR, this.color);
        }
    }

    /**
     * Getter for compProcess.
     * 
     * @return the compProcess
     */
    @Override
    public CompProcess getCompProcess() {
        return this.compProcess;
    }

    /**
     * Sets the compProcess.
     * 
     * @param compProcess the compProcess to set
     */
    public void setCompProcess(CompProcess compProcess) {
        this.compProcess = compProcess;
    }

    /**
     * Getter for size.
     * 
     * @return the size
     */
    @Override
    public Dimension getSize() {
        return this.size;
    }

    /**
     * Sets the size.
     * 
     * @param size the size to set
     */
    @Override
    public void setSize(Dimension size) {
        this.size = size;
        fireStructureChange(PROP_BLOCK_SIZE, this.size);
    }

    /**
     * Getter for location.
     * 
     * @return the location
     */
    @Override
    public Point getLocation() {
        return this.location;
    }

    /**
     * Sets the location.
     * 
     * @param location the location to set
     */
    @Override
    public void setLocation(Point location) {
        this.location = location;
        List<ICompConnection> conns = getOutgoingConnections();
        for (ICompConnection compConnection : conns) {
            CompConnection compConnection2 = ((CompConnection) compConnection);
            compConnection2.getConnectionLabel().changeLocation();
            if (compConnection2.getConnectionTrac() != null) {
                compConnection2.getConnectionTrac().changeLocation();
            }
        }
        conns = getIncomingConnections();
        for (ICompConnection compConnection : conns) {
            CompConnection compConnection2 = ((CompConnection) compConnection);
            compConnection2.getConnectionLabel().changeLocation();
            if (compConnection2.getConnectionTrac() != null) {
                compConnection2.getConnectionTrac().changeLocation();
            }
        }
        fireStructureChange(PROP_BLOCK_LOCATION, this.location);
    }

    /**
     * Getter for blockId.
     * 
     * @return the blockId
     */
    public String getBlockId() {
        return this.blockId;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.CompElement#isInput(java.lang.String)
     */
    @Override
    public boolean isInput(String string) {
        return true;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getBuildProcess".
     * 
     * @return
     */
    private ICompProcess getBuildProcess() {
        BlockEditorInput editorInput = new BlockEditorInput(getBlockId(), getCompName());
        return editorInput.getProcess();
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getRootNode".
     * 
     * @return
     */
    public ICompNode getRootNode() {
        ICompProcess buildProcess = getBuildProcess();

        List<ICompBlockExit> exits = buildProcess.getExits();
        for (ICompBlockExit compBlockExit : exits) {
            compBlockExit.setParent(this);
        }
        List<? extends CompElement> elements = buildProcess.getElements();
        for (CompElement compElement : elements) {
            compElement.setParent(this);
        }
        List<? extends ICompConnection> connections = buildProcess.getConnections();
        for (ICompConnection compConnection : connections) {
            compConnection.setParent(this);
        }
        for (ICompBlockExit compBlockExit : exits) {
            if (compBlockExit.isEnter()) {
                List<ICompConnection> otConns = ((CompBlockExit) compBlockExit).getOutgoingConnections();
                if (!otConns.isEmpty()) {
                    IGefNode target = otConns.get(0).getTarget();
                    if (target instanceof ICompNode) {
                        return (ICompNode) target;
                    }
                }
            }
        }
        return null;
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "getExitNames".
     * 
     * @return
     */
    public List<String> getExitNames() {
        List<String> list = new ArrayList<String>();
        ICompProcess buildProcess = getBuildProcess();
        List<ICompBlockExit> exits = buildProcess.getExits();
        for (ICompBlockExit compBlockExit : exits) {
            if (!compBlockExit.isEnter()) {
                list.add(compBlockExit.getCompName());
            }
        }
        return list;
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.dengues.core.process.CompElement#clone()
     */
    @Override
    public Object clone() {
        CompBlock object = (CompBlock) super.clone();
        object.setOutgoingConnections(new ArrayList<ICompConnection>());
        object.setIncomingConnections(new ArrayList<ICompConnection>());
        return object;
    }

    /**
     * Sets the compName.
     * 
     * @param compName the compName to set
     */
    public void setCompName(String compName) {
        this.compName = compName;
        fireStructureChange(PROP_BLOCK_NAME, compName);
    }

}
